<!--
   @Author: Li bowei
   @Date: 2022/9/14
   @Description:教师端首页 - 知识图谱
 -->
<template>
  <article class="map_container">
    <div class="map_header">
      <el-button
        size="small"
        @click="initData"
      >
        刷新
      </el-button>
    </div>
    <div
      id="graphContainer"
      class="graphContainer"
    >
      <Demo
        :styles="style"
        :init-data="graphData"
        :ring-function="RingFunction"
        :width="width"
        :height="height"
        @editForm="editForm"
      ></Demo>
    </div>
    <MenuForm
      ref="menu_form"
      @batchCreateNode="batchCreateNode"
      @batchCreateChildNode="batchCreateChildNode"
      @batchCreateSameNode="batchCreateSameNode"
      @createNode="createNode"
      @initNodeImage="initNodeImage"
      @initNodeContent="initNodeContent"
      @saveNodeImage="saveNodeImage"
      @saveNodeContent="saveNodeContent"
      @getDomain="getDomain"
      @getDomainGraph="getDomainGraph"
    >
    </MenuForm>
  </article>
</template>
<script>
import _ from 'lodash'
import Demo from '../components/Demo.vue'
import MenuForm from '../components/MenuForm.vue'
export default {
  components: {
    Demo,
    MenuForm
  },
  provide() {
    return {
      _thisKey: this._thisKey,
      Dset: this.Dset,
      updateLinkName: this.updateLinkName,
      editLinkName: this.editLinkName,
      deleteLinkName: this.deleteLinkName,
      quickAddNodes: this.btnQuickAddNode,
      createSingleNode: this.createSingleNode,
      updateCoordinateOfNode: this.updateCoordinateOfNode,
      getNodeDetail: this.getNodeDetail
    }
  },
  data() {
    return {
      areasRelevancy: false,
      extractStatus: false,
      width: null,
      height: null,
      thisView: null,
      d3: null,
      style: {},
      graphData: {
        nodes: [],
        links: []
      },
      RingFunction: [
        {
          title: '新建',
          icon: {
            type: 'text',
            content: '新建'
          },
          defaultEvent: (d, _this, d3) => {
            this.$refs.menu_form.initBatchAddChild(true, 'batchAddChild', d, this.domain)
          }
        },
        {
          title: '编辑',
          icon: {
            type: 'text',
            content: '编辑'
          },
          defaultEvent: (d, _this, d3) => {
            _this.$nextTick(() => {
              const formNode = {
                uuid: d.uuid,
                name: d.name,
                r: parseInt(d.r),
                color: d.color
              }
              _this.$emit('editForm', true, 'nodeEdit', formNode, _this.domainId)
            })
          },
          childrens: []
        },
        {
          title: '删除',
          icon: {
            type: 'text',
            content: '删除'
          },
          defaultEvent: (d, _this, d3) => {
            const data = { domain: _this.domain, nodeId: d.uuid }
            this.$confirm('此操作将会永久删除该节点及其相关关系，是否继续', '提示', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning'
            }).then(() => {
              this.delNode(d, _this, data)
            })
          },
          childrens: []
        },
        {
          title: '连线',
          icon: {
            type: 'text',
            content: '连线'
          },
          defaultEvent: (data, _this, d3) => {
            this.createLink(data)
          },
          childrens: []
        }
      ]
    }
  },
  mounted() {
    this.initData()
  },
  methods: {

    _thisKey(item) {
      this.thisView = item
    },
    Dset(item) {
      this.d3 = item
    },
    // 初始化数据
    initData() {
      // 初始化图表占位大小
      this.$nextTick(() => {
        this.width = document.getElementsByClassName('graphContainer')[0].offsetWidth
        this.height = document.getElementsByClassName('graphContainer')[0].offsetHeight
        // this.height = window.screen.height
        this.style = {
          width: this.width + 'px',
          height: this.height + 'px'
        }
        console.log('mounted -> 初始化图表占位大小', this.width, this.height, this.style)
        this.getDomainGraph()
      })
    },
    // 获取图表数据
    getDomainGraph() {
      this.graphData = {
        nodes: [],
        links: []
      }
      setTimeout(() => {
        this.graphData.nodes = [
          {
            fx: 321.85237499483037,
            r: 30,
            fy: 148.93523907703343,
            color: '#ff4500',
            name: '上山打老虎2',
            uuid: '93',
            labels: [
              '11111'
            ]
          },
          {
            fx: 520.7929577914176,
            r: '75',
            fy: 538.6298624349708,
            color: '#ff4500',
            domain: '11111',
            name: 'mysql',
            uuid: '107',
            labels: [
              '11111'
            ]
          },
          {
            fx: 555.0738074493642,
            r: 30,
            fy: 319.4484048940516,
            color: '#ff4500',
            name: '下一级',
            uuid: '114',
            labels: [
              '11111'
            ]
          },
          {
            fx: 316.20437805499614,
            r: 30,
            fy: 802.1414854864878,
            color: '#ff4500',
            name: 'mysql',
            uuid: '127',
            labels: [
              '11111'
            ]
          },
          {
            fx: 937.0670973535705,
            r: 30,
            fy: 495.4696441973311,
            color: '#ff4500',
            name: 'sql语句',
            uuid: '128',
            labels: [
              '11111'
            ]
          },
          {
            fx: 127.69283005162788,
            r: 30,
            fy: 241.9396446125305,
            color: '#ff4500',
            name: '引擎',
            uuid: '129',
            labels: [
              '11111'
            ]
          },
          {
            fx: 728.9730804671917,
            r: '30',
            fy: 158.44219059888485,
            color: '#ff4500',
            domain: '11111',
            name: 'danna',
            uuid: '130',
            labels: [
              '11111'
            ]
          },
          {
            fx: 642.9853794691351,
            r: 30,
            fy: 0.6325264635596568,
            color: '#ff4500',
            name: '上山打老虎',
            uuid: '131',
            labels: [
              '11111'
            ]
          },
          {
            fx: 672.2688561879958,
            r: 30,
            fy: 758.858194225144,
            color: '#ff4500',
            name: '上山打老虎3',
            uuid: '150',
            labels: [
              '11111'
            ]
          }
        ]
        this.graphData.links = [
          {
            sourceId: '131',
            targetId: '93',
            name: 'hhhhhh',
            uuid: '159'
          },
          {
            sourceId: '107',
            targetId: '130',
            name: '傻傻傻',
            uuid: '158'
          },
          {
            sourceId: '130',
            targetId: '114',
            name: '包含',
            uuid: '72'
          },
          {
            sourceId: '127',
            targetId: '129',
            name: '789ssasa',
            uuid: '70'
          },
          {
            sourceId: '127',
            targetId: '129',
            name: '引擎 ---> mysql',
            uuid: '86'
          },
          {
            sourceId: '127',
            targetId: '128',
            name: '包含',
            uuid: '85'
          }
        ]
        console.log('获取图表数据 ---> ', this.graphData)
      }, 500)
    },
    // 更新位置信息
    updateCoordinateOfNode(nodes) {
      const data = { domain: '更新节点位置信息', nodes }
      console.log(data)
    //   this.$get('/updateNode',data).then((result) => {})
    },
    // 添加连线
    createLink(data) {
      console.log(data)
      //   this.$get('/createLink',data).then((result) => {
      const d = {
        sourceId: data.sourceId,
        targetId: data.targetId,
        name: '哈哈哈',
        uuid: _.size(this.graphData.links)
      }
      this.graphData.links.push(d)
    //   })
    },
    // 更新连线名称
    updateLinkName(sdata) {
      const _this = this
      this.$prompt('请输入关系名称', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        inputValue: sdata.cname
      }).then(function(res) {
        const value = res.value
        const data = {
          domain: _this.domain,
          shipId: sdata.uuid,
          shipName: value
        }
        console.log('更新连线名称', [sdata, res, data])
        // this.$get('/updateLink',data).then((result) => {
        const newShip = {
          uuid: sdata.uuid,
          name: res.value
        }
        _this.graphData.links.forEach(function(m) {
          if (m.uuid == newShip.uuid) {
            m.name = newShip.name
          }
        })
        // })
      })
        .catch(function() {})
    },
    editForm(flag, action, data, domainId) {
      this.$refs.menu_form.initNode(flag, action, data, domainId)
    },
    // 画布直接添加节点
    createSingleNode(left, top) {
      const data = { name: '', r: 30 }
      data.domain = this.domain
      const newNode = {
        fx: 321.85237499483037,
        r: 30,
        fy: 148.93523907703343,
        color: '#ff4500',
        domain: '00000',
        name: '之一 · ' + _.size(this.graphData.nodes),
        uuid: _.size(this.graphData.nodes) + Math.floor(Math.random() * 9888899),
        labels: ['00000']
      }
      _.assignIn(newNode, {
        x: left,
        y: top,
        fx: left,
        fy: top,
        r: parseInt(newNode.r),
        image: ''
      })
      this.graphData.nodes.push(newNode)
    },
    // 快速添加
    btnQuickAddNode() {
      this.$refs.menu_form.init(true, 'batchAdd', this.domain)
    },
    // 一次性获取富文本和图片
    getNodeDetail(nodeId, left, top) {
      console.log('一次性获取富文本和图片', nodeId, left, top)
      // const data = { domainId: this.domainId, nodeId }
      // this.$get('/info', data).then((result) => {
      //   if (result.data) {
      //     this.$refs.node_richer.init(result.data.content, result.data.imageList, left, top)
      //   } else {
      //     this.$message.warning('暂时没有更多数据')
      //   }
      // })
    },
    // 删除连线
    deleteLinkName(sdata) {
      const _this = this
      _this.$confirm('此操作将删除该关系(不可恢复), 是否继续?', '三思而后行', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        // this.$get('/deleteLink', sdata).then((result) => {
        let j = -1
        for (let i = 0; i < _this.graphData.links.length; i++) {
          if (_this.graphData.links[i].uuid == sdata.uuid) {
            j = i
            break
          }
        }
        if (j >= 0) {
          _this.graphData.links.splice(j, 1)
        }
        // })
        console.log('删除连线', sdata)
      }).catch(function() {
        _this.$message.info('已取消删除')
      })
    },
    // 删除节点
    delNode(d, _this, data) {
      //   this.$get('/deleteNode', data).then((result) => {
      // 删除节点对应的关系
      for (let i = 0; i < _this.graph.links.length; i++) {
        if (_this.graph.links[i].uuid === d.uuid) {
          _this.graph.links.splice(i, 1)
          i = i - 1
        }
      }
      // 找到对应的节点索引
      let j = -1
      for (let i = 0; i < _this.graph.nodes.length; i++) {
        if (_this.graph.nodes[i].uuid === d.uuid) {
          j = i
          break
        }
      }
      if (j >= 0) {
        _this.selectNode.nodeId = 0
        _this.graph.nodes.splice(j, 1) // 根据索引删除该节点
        _this.$message.success('操作成功')
        _this.updateGraph()
      }
      //   })
    },
    // 批量添加节点
    batchCreateNode(param) {
      const data = {
        domain: this.domain,
        sourceName: param.sourceNodeName,
        targetNames: param.targetNodeNames,
        relation: param.relation
      }
      console.log('批量添加节点 , batchCreateNode', data)
      const resultArr = param.targetNodeNames.split(',')
      const f = {
        r: 30,
        color: '#ff4500',
        name: param.sourceNodeName,
        uuid: _.size(this.graphData.nodes) + Math.floor(Math.random() * 199),
        labels: [this.domain]
      }
      const resultNodesArr = [f]
      const resultLinksArr = []
      _.each(resultArr, (result) => {
        const node = {
          r: 30,
          color: '#ff4500',
          name: result,
          uuid: _.size(this.graphData.nodes) + Math.floor(Math.random() * 9999),
          labels: [this.domain]
        }
        const link = {
          sourceId: f.uuid,
          targetId: node.uuid,
          name: param.relation,
          uuid: _.size(this.graphData.links) + Math.floor(Math.random() * 2333)
        }
        resultNodesArr.push(node)
        resultLinksArr.push(link)
      })
      //  this.$post('/addNode', param).then((result) => {
      //     // 把不存在于画布的节点添加到画布
      console.log(resultNodesArr, resultLinksArr)
      this.mergeNodeAndLink(resultNodesArr, resultLinksArr)
      this.$message.success('操作成功')
      //   })
    },
    // 批量添加子节点
    batchCreateChildNode(param) {
      const data = {
        domain: '',
        sourceId: param.sourceUuid,
        targetNames: param.targetNodeNames,
        relation: param.relation
      }
      const resultArr = param.targetNodeNames.split(',')
      const resultNodesArr = []
      const resultShipsArr = []
      _.each(resultArr, (result) => {
        const nodes = {
          r: 30,
          color: '#ff4500',
          name: result,
          uuid: _.size(this.graphData.nodes) + Math.floor(Math.random() * 909992),
          labels: [this.domain]
        }
        const link = {
          sourceId: param.sourceUuid,
          targetId: nodes.uuid,
          name: param.relation,
          uuid: _.size(this.graphData.links) + Math.floor(Math.random() * 789919)
        }
        resultNodesArr.push(nodes)
        resultShipsArr.push(link)
      })
      // TODO: 调接口
      // 把不存在于画布的节点添加到画布
      this.mergeNodeAndLink(resultNodesArr, resultShipsArr)
      // 重新绘制
      this.$message.success('操作成功')
      console.log('批量添加子节点 , batchCreateChildNode', data, resultNodesArr, resultShipsArr)
    },

    // 合并节点和连线
    mergeNodeAndLink(newNodes, newLinks) {
      const _this = this
      newNodes.forEach(function(m) {
        const sobj = _this.graphData.nodes.find(function(x) {
          return x.uuid === m.uuid
        })
        if (typeof sobj == 'undefined') {
          _this.graphData.nodes.push(m)
        }
      })
      newLinks.forEach(function(m) {
        const sobj = _this.graphData.links.find(function(x) {
          return x.uuid === m.uuid
        })
        if (typeof sobj == 'undefined') {
          _this.graphData.links.push(m)
        }
      })
    },
    // 批量添加同级节点
    batchCreateSameNode(param) {
      const data = {
        domain: this.domain,
        sourceNames: param.sourceNodeName
      }
      console.log(data)
      // this.$get('/createSameNode',data).then((result) => {
      //   if (result.code == 200) {
      //     //把不存在于画布的节点添加到画布
      //     this.mergeNodeAndLink(result.data, null);
      //     this.$message({
      //       message: "操作成功",
      //       type: "success",
      //     });
      //   }
      // });
    },
    // 创建节点
    createNode(graphNode) {
      const data = graphNode
      data.domain = this.domain
      const _this = this
      // this.$get('/createNode',data).then((result) => {
      // 删除旧节点，由于我们改变的是属性，不是uuid,此处我们需要更新属性，或者删除节点重新添加
      const newNode = {
        fx: 0,
        r: data.r,
        fy: 0,
        color: data.color,
        name: data.name,
        uuid: data.uuid,
        labels: []
      }
      for (let i = 0; i < _this.graphData.nodes.length; i++) {
        if (_this.graphData.nodes[i].uuid == graphNode.uuid) {
          newNode.fx = _this.graphData.nodes[i].fx
          newNode.fy = _this.graphData.nodes[i].fy
          newNode.labels = _this.graphData.nodes[i].labels
          _this.graphData.nodes.splice(i, 1)
        }
      }
      _this.graphData.nodes.push(newNode)
      // })
    },
    // 初始化节点添加的图片
    initNodeImage(data) {
      console.log(data)
      // TODO: 调接口
      // let param = { domainId: data.domainId, nodeId: data.nodeId };
      // this.$get('/nodeImage',param).then((response) => {
      //   if (response.code == 200) {
      //     if (response.data) {
      //       let nodeImageList = [];
      //       for (let i = 0; i < response.data.length; i++) {
      //         nodeImageList.push({
      //           file: response.data[i].fileName,
      //           imageType: response.data[i].imageType,
      //         });
      //         this.$refs.menu_form.initImage(nodeImageList);
      //       }
      //     } else {
      //       this.$message.warning("暂时没有更多数据");
      //     }
      //   }
      // });
    },
    // 初始化节点富文本内容
    initNodeContent(data) {
      console.log(data)
      // TODO: 调接口
      // const param = { domainId: data.domainId, nodeId: data.nodeId }
      // this.$get('/nodeIno',param).then((response) => {
      //     if (response.data) {
      //       this.$refs.menu_form.initContent(response.data.content)
      //     } else {
      //       this.$message.warning('暂时没有更多数据')
      //     }
      // })
    },
    saveNodeImage(data) {
      console.log(data)
      // const image = data.imagePath
      // const nodeId = data.nodeId
      // const _this = this
      // TODO: 调接口
      // this.$post('/saveNode',data).then((result) => {
      //     _this.graphData.nodes
      //       .filter((n) => n.uuid == nodeId)
      //       .map((m) => {
      //         m.image = image
      //         return m
      //       })
      //     _this.$message({
      //       message: '操作成功',
      //       type: 'success'
      //     })
      // })
    },
    // 上传富文本
    saveNodeContent(data) {
      console.log(data)
      // TODO: 调接口
      //  this.$post('/upload',data).then((result) => {
      //   if (result.code == 200) {
      //     this.$message({ message: '操作成功', type: 'success' })
      //   }
      // })
    },
    getDomain(pageIndex) {
      console.log(pageIndex)
    }

  }
}
</script>
<style scoped lang='scss'>
.map_container {
  height: 100%;

  .map_header {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    padding: 8px;
    padding-right: 18px;
  }

  .graphContainer {
    height: calc(100vh - 50px);
    background: white;
  }
}

.extract {
  .footer {
    display: flex;
    justify-content: flex-end;
    margin-top: 16px;
    // padding-right: 40px;
  }
}
</style>
